package Differ

import (
	"errors"
	"reflect"
)

type setType struct {
}

func (e *setType) DifferByKey(list ...any) (bool, error) {
	for i := 0; i < len(list); i++ {
		if i < 2 {
			t := reflect.TypeOf(list[i])
			if t.Kind() != reflect.Map {
				return false, errors.New("参数必须是 map 类型")
			}
		} else {
			t := reflect.TypeOf(list[i])
			if t.Kind() != reflect.Pointer {
				return false, errors.New("参数必须是 &map 类型")
			}
			if t.Elem().Kind() != reflect.Map {
				return false, errors.New("参数必须是 &map 类型")
			}

		}

	}

	if len(list) < 2 {
		return false, errors.New("函数格式：DifferByKey(srcList,dstList)")
	}

	srcList := make(map[interface{}]interface{}, 0)
	for _, k := range reflect.ValueOf(list[0]).MapKeys() {
		srcList[k.Interface()] = k.Interface()
	}

	dstList := make(map[interface{}]interface{}, 0)
	for _, k := range reflect.ValueOf(list[1]).MapKeys() {
		dstList[k.Interface()] = k.Interface()
	}

	// 范例：Differ.Set.DifferByKey(srcMap, dstMap)
	if len(list) == 2 {
		addList := make(map[interface{}]interface{})
		delList := make(map[interface{}]interface{})
		eqlList := make(map[interface{}]interface{})
		e.diffA2B(srcList, dstList, addList, eqlList)
		e.diffA2B(dstList, srcList, delList, eqlList)
		return len(addList) != 0 && len(delList) != 0, nil
	}

	// 范例：Differ.Set.DifferByKey(srcMap, dstMap, &addList, &delList)
	if len(list) == 4 {
		addList := make(map[interface{}]interface{})
		delList := make(map[interface{}]interface{})
		eqlList := make(map[interface{}]interface{})

		// 检测数据类型
		t2 := reflect.TypeOf(list[2]).Elem()
		t3 := reflect.TypeOf(list[3]).Elem()
		if reflect.TypeOf(addList).Kind() != t2.Kind() || reflect.TypeOf(delList).Kind() != t3.Kind() {
			return false, errors.New("函数格式不支持")
		}

		e.diffA2B(srcList, dstList, addList, eqlList)
		e.diffA2B(dstList, srcList, delList, eqlList)

		add := reflect.ValueOf(list[2])
		for k, _ := range addList {
			add.Elem().SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(&k))
		}
		del := reflect.ValueOf(list[3])
		for k, _ := range delList {
			del.Elem().SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(&k))
		}

		return len(addList) != 0 && len(delList) != 0, nil
	}

	// 范例：Differ.Set.DifferByKey(srcMap, dstMap, &addList, &delList, &eqlList)
	if len(list) == 5 {
		addList := make(map[interface{}]interface{})
		delList := make(map[interface{}]interface{})
		eqlList := make(map[interface{}]interface{})

		// 检测数据类型
		t2 := reflect.TypeOf(list[2]).Elem()
		t3 := reflect.TypeOf(list[3]).Elem()
		t4 := reflect.TypeOf(list[4]).Elem()
		if reflect.TypeOf(addList).Kind() != t2.Kind() || reflect.TypeOf(delList).Kind() != t3.Kind() || reflect.TypeOf(eqlList).Kind() != t4.Kind() {
			return false, errors.New("函数格式不支持")
		}

		e.diffA2B(srcList, dstList, addList, eqlList)
		e.diffA2B(dstList, srcList, delList, eqlList)

		add := reflect.ValueOf(list[2])
		for k, _ := range addList {
			add.Elem().SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(&k))
		}
		del := reflect.ValueOf(list[3])
		for k, _ := range delList {
			del.Elem().SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(&k))
		}
		eql := reflect.ValueOf(list[4])
		for k, _ := range eqlList {
			eql.Elem().SetMapIndex(reflect.ValueOf(k), reflect.ValueOf(&k))
		}

		return len(addList) != 0 && len(delList) != 0, nil
	}

	return false, errors.New("函数格式不支持")
}

func (e *setType) diffA2B(srcList map[interface{}]interface{}, dstList map[interface{}]interface{}, addList map[interface{}]interface{}, eqlList map[interface{}]interface{}) {
	e.clear(addList)
	e.clear(eqlList)

	for k, v := range dstList {
		_, ok := srcList[k]
		if !ok {
			addList[k] = v
		} else {
			eqlList[k] = v
		}
	}
}

func (e *setType) clear(list map[interface{}]interface{}) {
	for k := range list {
		delete(list, k)
	}
}
